package com.quanyan.club.mq.consumer;

import com.alibaba.fastjson.JSON;
import com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
import com.alibaba.rocketmq.common.message.MessageExt;
import com.quanyan.club.constants.ClubConstants;
import com.quanyan.club.entity.db.TbClubWithdrawalsApply;
import com.quanyan.club.entity.db.TbClubWithdrawalsApplyExample;
import com.quanyan.club.entity.db.TbClubWithdrawalsRecord;
import com.quanyan.club.mapper.TbClubWithdrawalsApplyMapper;
import com.quanyan.club.mapper.TbClubWithdrawalsRecordMapper;
import com.quanyan.club.mq.constant.MqConstant;
import com.quanyan.club.service.ClubFinanceMgmService;
import com.quanyan.club.service.ClubWidthdrawService;
import com.quanyan.club.service.CppService;
import com.quanyan.common.constants.Constants;
import com.quanyan.common.utils.ObjectUtil;
import com.quanyan.mq.enums.MqConsumerStatus;
import com.quanyan.mq.mq.consumer.AbstractMqConsumer;
import com.quanyan.mq.mq.consumer.MqTopic;
import com.quanyan.orderpay.response.mq.WithdrawTransferNotify;
import com.quanyan.orderpay.service.OrderPayService;

import org.mybatis.spring.SqlSessionTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;

/**
 * Created by zhuo.shi on 2016/7/13. 俱乐部提现，支付宝提现，支付系统回调处理类
 */
@Component
public class ClubWithdrawConsumer extends AbstractMqConsumer {

    private static Logger logger = LoggerFactory.getLogger(ClubWithdrawConsumer.class);

    @Autowired
    private ClubWidthdrawService clubWidthdrawService;
    @Autowired
    private TbClubWithdrawalsApplyMapper withdrawalsApplyMapper;
    @Autowired
    private SqlSessionTemplate sqlSessionTemplate;
    @Autowired
    private TbClubWithdrawalsRecordMapper withdrawalsRecordMapper;
    @Autowired
    private CppService cppService;

    @Value("${mq.nameServer.address}")
    private String nameServerAddress;

//    @PostConstruct
//    public void run() {
//        super.start();
//    }

    @Override
    @Transactional
    protected MqConsumerStatus process(List<MessageExt> messages, ConsumeConcurrentlyContext context) {
        MessageExt messageExt = messages.get(0);
        String msgId = messageExt.getKeys();
        byte[] bodyByte = messageExt.getBody();

        WithdrawTransferNotify notify = null;
        try {
            notify = (WithdrawTransferNotify) ObjectUtil.toObject(bodyByte);
        } catch (Exception e) {
            logger.error("俱乐部提现回调出错{}", e.getMessage());
            return MqConsumerStatus.RE_CONSUME_LATER;
        }
        logger.info("提现回调notify={}", JSON.toJSON(notify));

        //1. 过滤，只处理本系统的提现业务
        String systemCode = notify.getSourceSystemCode();
        String bussinessCode = notify.getSourceBusinessCode();
        if (!systemCode.equals(Constants.CLUB_SYSTEM_CODE) || !bussinessCode.equals(Constants.CLUB_WITHDRAW_BUSINESS_CODE)) {
            return MqConsumerStatus.RE_CONSUME_LATER;
        }

        String withdrawNo = notify.getWithdrawNo(); //支付系统生成的提现申请流水号

        //2. 查询出此条俱乐部提现申请
        TbClubWithdrawalsApplyExample example = new TbClubWithdrawalsApplyExample();
        TbClubWithdrawalsApplyExample.Criteria criteria = example.createCriteria();
        criteria
                .andWithdrawNoEqualTo(withdrawNo)
                .andIsDeleteEqualTo(Constants.IS_DELETE_FALSE);
        if (notify.getTag()){
            criteria.andWithdrawalsStatusNotEqualTo((byte)3);        //公司已付款，提现已成功，不能再次更新俱乐部线上资金
        }else {
            criteria.andWithdrawalsStatusNotEqualTo((byte)4);       //已经失败了，再次回调，不再恢复冻结资金
        }
        List<TbClubWithdrawalsApply> applies = withdrawalsApplyMapper.selectByExample(example);
        if (applies == null || applies.isEmpty()) {
            logger.warn("提现回调直接返回：可能原因，1. 提现流水号{}不存在，2. 或者公司已付款，提现已成功，重复的回调，3. 或已更新提现失败状态，再次回调不再次恢复冻结资金", withdrawNo);
            return MqConsumerStatus.RE_CONSUME_LATER;
        }
        TbClubWithdrawalsApply record = applies.get(0);

        int clubId = record.getClubId();        //俱乐部id
        String reason = notify.getReason();     //付款成功或失败原因
        BigDecimal amount = notify.getAmount(); //提现金额，返回的单位为: 元

        if (notify.getTag()) {      //如果付款成功
            //3. 更新俱乐部线上账户资金
            Map<String, Object> map = new HashMap<>();
            map.put("clubId", clubId);
            map.put("withdrawAmount", amount);
            int updateret = sqlSessionTemplate.update("updateClubAccountTotalAndFreezeFund", map);
            if (updateret != 1) {
                logger.error("俱乐部提现回调，扣除俱乐部{}线上金额失败。", record.getClubId());
                reason += "俱乐部提现回调，扣除线上金额失败";
            }else {
                //4. 记录俱乐部提现流水
                TbClubWithdrawalsRecord withdrawalsRecord = new TbClubWithdrawalsRecord();
                withdrawalsRecord.setApplyNo(notify.getApplyNo());
                withdrawalsRecord.setBatchNo(notify.getBatchNo());
                withdrawalsRecord.setClubId(clubId);
                withdrawalsRecord.setAccountType(ClubConstants.WITHDRAW_BY_WEIXIN);
                withdrawalsRecord.setWithdrawalsName(notify.getName());
                withdrawalsRecord.setWithdrawalsAccount(notify.getAccountNo());
                withdrawalsRecord.setMoney(amount);
                withdrawalsRecord.setBalance(clubWidthdrawService.getUsableWidthdrawAmount(clubId)); //此俱乐部线上账户的余额
                withdrawalsRecord.setUid(record.getUid());
                withdrawalsRecordMapper.insertSelective(withdrawalsRecord);

                //推送提现成功消息
                cppService.pushWithdrawNotifyMessage(record, true, reason);
            }
        }else {
            //恢复冻结资金
            Map<String, Object> map = new HashMap<>();
            map.put("clubId", clubId);
            map.put("withdrawAmount", amount);
            int updateret = sqlSessionTemplate.update("updateClubAccountUsablelAndFreezeFund", map);
            if (updateret != 1) {
                logger.error("俱乐部提现回调，解冻俱乐部{}线上金额失败。", record.getClubId());
                reason += "俱乐部提现回调，解冻线上金额失败";
            }
            //推送提现失败消息
            cppService.pushWithdrawNotifyMessage(record, false, reason);
        }

        //5. 更新此笔提现记录
        if (notify.getTag()) {
            record.setWithdrawalsStatus((byte) 3);  //付款成功
        } else {
            record.setWithdrawalsStatus((byte) 4);  //付款失败
        }
        record.setBatchNo(notify.getBatchNo());     //支付系统生成的批次号
        record.setRemark(reason);       //第三方支付系统返回的，成功或者失败原因 + 自己系统的原因
        record.setAuditStatus((byte) 2);             //审核通过
        withdrawalsApplyMapper.updateByPrimaryKeySelective(record);

        return MqConsumerStatus.CONSUMER_SUCCESS;
    }

    @Override
    protected String getConsumerGroup() {
        return MqConstant.CLUB_WITHDRAW_GROUP_NAME;
    }

    @Override
    protected String getNameServerAddress() {
        return nameServerAddress;
    }

    @Override
    protected String getInstanceName() {
        return MqConstant.CLUB_WITHDRAW_INSTANCE_NAME;
    }

    @Override
    protected MqTopic[] getMqTopics() {
        MqTopic[] mqTopics = new MqTopic[1];
        mqTopics[0] = new MqTopic(OrderPayService.TOPIC_WITHDRAW_CALLBACK_NOTIFY, "*");
        return mqTopics;
    }
}
